package com.alks.common.config.interceptor;

import jodd.util.StringUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.ContentCachingResponseWrapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: chen
 * @date: 2025/1/16
 * @description: 全局脱敏，身份证，姓名，手机号等
 */
//@Component
public class ResponseSensitiveInterceptor implements HandlerInterceptor {

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if (!(response instanceof ContentCachingResponseWrapper)) {
            return;
        }
        String token = request.getHeader("Authorization");
        if (StringUtil.isEmpty(token)) {
            return;
        }

        // 包装响应对象
        ContentCachingResponseWrapper responseWrapper = (ContentCachingResponseWrapper) response;

        // 获取响应体内容
        String responseBody =
                new String(responseWrapper.getContentAsByteArray(), StandardCharsets.UTF_8);

        String sensitiveBody = maskSensitiveInfo(responseBody);

        // 关键步骤：将脱敏后的内容写回响应
        responseWrapper.resetBuffer(); // 清空原有缓存
        byte[] maskedBytes = sensitiveBody.getBytes(StandardCharsets.UTF_8);
        responseWrapper.setContentLength(maskedBytes.length); // 更新内容长度
        responseWrapper.getOutputStream().write(maskedBytes); // 写入新内容

        // 复制响应内容到实际输出流
        responseWrapper.copyBodyToResponse();
    }

    public static String maskSensitiveInfo(String input) {
        if (input == null || input.isEmpty()) {
            return input;
        }

        String result = input;

        // 处理顺序建议：结构化数据优先 -> 非结构化数据最后
        result = processBankCard(result);
        result = processPhoneNumber(result);
        result = processIdCard(result);
        result = processEmail(result);
        result = processChineseName(result);
        result = maskAddressEnhanced(result);
        result = replaceKeywords(result); // 关键词替换放在最后

        return result;
    }

    // region 结构化数据处理 - - - - - - - - - - - - - - - - - - - -

    // 银行卡号（16-19位数字）
    private static String processBankCard(String input) {
        return Pattern.compile("\\b\\d{16,19}\\b")
                .matcher(input)
                .replaceAll(mr -> mr.group().replaceAll("(\\d{4})\\d{8,11}(\\d{4})", "$1****$2"));
    }

    // 手机号（11位数字，1开头）
    private static String processPhoneNumber(String input) {
        return Pattern.compile("\\b1[3-9]\\d{9}\\b")
                .matcher(input)
                .replaceAll(mr -> mr.group().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
    }

    // 身份证号（支持15位旧版和18位新版）
    private static String processIdCard(String input) {
        return Pattern.compile("\\b\\d{15}\\b|\\b\\d{17}[\\dXx]\\b")
                .matcher(input)
                .replaceAll(mr -> {
                    String id = mr.group();
                    if (id.length() == 15) {
                        return id.replaceAll("(\\d{4})\\d{7}(\\d{4})", "$1*******$2");
                    } else {
                        return id.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1**********$2");
                    }
                });
    }

    // 电子邮箱（用户名脱敏）
    private static String processEmail(String input) {
        return Pattern.compile("\\b\\w+([.-]?\\w+)*@\\w+([.-]?\\w+)*\\.\\w{2,4}\\b")
                .matcher(input)
                .replaceAll(mr -> {
                    String email = mr.group();
                    int atIndex = email.indexOf('@');
                    if (atIndex > 2) {
                        return email.charAt(0) + "***" + email.substring(atIndex - 1);
                    }
                    return email;
                });
    }

    // 中文姓名（保留姓氏）
    // 常见中文姓氏（可扩展）
    private static final String[] COMMON_SURNAMES = {
            "丁","万","严","乔","于","云","付","代","令","任","伍","何","余","侯","保","俞","候","倪","兰","关","冉","农","冯",
            "冷","凡","刘","包","匡","单","卜","占","卢","卿","古","史","叶","向","吕","吴","周","唐","喻","备","夏","外","天",
            "奥","姚","姜","娄","孔","孙","孟","安","宋","宗","官","客","封","小","尚","尹","居","屈","岑","岩","岳","崔","左",
            "巫","常","干","幸","庄","庞","康","庹","廉","廖","开","张","彭","徐","得","惠","想","成","戴","扈","扬","扶","揭",
            "撒","支","敬","文","方","施","明","易","晏","普","曹","曾","朱","李","杜","杨","板","林","柏","柯","柳","柴","桂",
            "梁","梅","樊","欢","欧","段","殷","母","毛","江","汤","汪","沈","沙","洒","洪","海","涂","温","游","滕","满","潘",
            "濮","焦","熊","牛","牟","王","玲","琴","甄","甘","田","申","白","盘","盛","眭","瞿","石","祖","祝","禤","秦","程",
            "穆","章","符","简","米","粟","素","红","缪","罗","美","耿","聂","肖","胡","舒","艾","花","苏","苑","苗","范","莫",
            "萧","葛","董","蒋","蒙","蒲","蓝","蔚","蔡","薄","薛","虞","袁","裴","覃","詹","许","谢","谭","贺","贾","赖","赧",
            "赵","路","蹇","车","辛","达","连","邓","邝","邢","邬","邱","邵","邹","郁","郅","郑","郜","郝","郭","鄢","重","金",
            "钟","钱","闫","闵","闻","阳","阿","陆","陈","陶","雍","雷","露","韦","韩","项","顾","颜","饶","马","骆","高","魏",
            "鲁","麻","黄","黎","龙","龚"
    };


    // 常见非姓名关键词（黑名单）
    private static final String[] NON_NAME_KEYWORDS = {
            "公司", "集团", "部门", "行政", "银行", "分行", "分局", "中心"
            // 补充更多业务相关关键词...
    };

    // 中文姓名脱敏处理（增强版）
    private static String processChineseName(String input) {
        // 构建姓氏正则表达式
        String surnameRegex = String.join("|", COMMON_SURNAMES);

        // 匹配规则：姓氏 + 1~3个中文字符，且不在黑名单中
        Pattern pattern = Pattern.compile(
                "(?<!\\S)([" + surnameRegex + "])([\u4e00-\u9fa5]{1,3})(?!\\S)|" + // 精准匹配
                        "\\b[\u4e00-\u9fa5]{2,4}\\b" // 兜底匹配（需二次校验）
        );

        Matcher matcher = pattern.matcher(input);
        StringBuilder sb = new StringBuilder();

        while (matcher.find()) {
            String matched = matcher.group();
            if (isFalsePositive(matched)) {
                matcher.appendReplacement(sb, matched); // 保留原内容
                continue;
            }
            // 执行脱敏
            String masked = matched.replace(matched.charAt(1), '*');
            matcher.appendReplacement(sb, masked);
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    // 排除误判检查
    private static boolean isFalsePositive(String text) {
        // 检查黑名单关键词
        for (String keyword : NON_NAME_KEYWORDS) {
            if (text.contains(keyword)) return true;
        }
        // 检查是否包含非姓氏组合
        return Arrays.stream(COMMON_SURNAMES).noneMatch(text::startsWith);
    }
    // endregion

    // region 非结构化数据处理 - - - - - - - - - - - - - - - - - - - -

    // 敏感词替换（支持多次匹配）
    private static String replaceKeywords(String input) {
        String[] keywords = {"荣阳", "荣信", "荣越", "荣廷", "荣创", "步峰"};
        for (String keyword : keywords) {
            input = input.replace(keyword, "XX");
        }
        return input;
    }

    // 地址脱敏处理
    public static String maskAddressEnhanced(String address) {
//        String regex = "((黑龙江|吉林|辽宁|河北|山西|陕西|甘肃|青海|山东|江苏|浙江|安徽|福建|江西|河南|湖北|湖南|广东|海南|四川|贵州" +
//                "|云南|陕西|台湾|北京|天津|上海|重庆|内蒙古|广西|西藏|宁夏|新疆|香港|澳门)省?|.+?(?:自治区|行政区|特别行政区))(.+?[市县区])(.+?[乡村镇街道])(.+?[组栋号])(.+?)(\"?)";
//        return address.replaceAll(regex, "$1$2$3*********");
        return address.replaceAll("([市县区])([^\"]+)(\")", "$1*********$3");
    }

}